package com.bolt.support.spring.jpa.id;

import com.bolt.common.utils.SnowflakeIdWorker;
import com.bolt.common.utils.StrUtil;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Properties;

/**
 * @GeneratedValue(generator = "snowFlakeId")
 * @GenericGenerator(name = "snowFlakeId", strategy = "com.bolt.support.spring.jpa.id.SnowflakeIdGenerator")
 * 基于twitter的分布式自增ID生成策略
 */
public class SnowflakeIdGenerator implements IdentifierGenerator, Configurable {
    private SnowflakeIdWorker idWorker = null;

    public String workId;

    public String dataId;


    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        workId = params.getProperty("workId");
        dataId = params.getProperty("dataId");
        if (StrUtil.isEmpty(workId) || StrUtil.isEmpty(dataId)) {
            InputStream is = SnowflakeIdGenerator.class.getResourceAsStream("/snowflake.properties");
            try {
                params.load(is);
            } catch (IOException e) {
                throw new RuntimeException("加载snowflake文件异常" + e.getMessage(), e);
            }
            workId = params.getProperty("workId");
            dataId = params.getProperty("dataId");
        }
        if (StrUtil.isEmpty(workId)) {
            throw new MappingException("param named \"workId\" is required for foreign id generation strategy");
        }
        if (StrUtil.isEmpty(dataId)) {
            throw new MappingException("param named \"dataId\" is required for foreign id generation strategy");
        }
        idWorker = new SnowflakeIdWorker(Long.valueOf(workId), Long.valueOf(dataId), type.getReturnedClass());

    }

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        return idWorker.nextId();
    }
}

 